#This app should do the following:
#Current list of courses are first added to the list (this should be approved by admins)
#students select the courses they are enrolled to, using a simple dropdown menu with multiple choices (fine if restriced to iiserk.net a/c otherwise should be approved by admins)
#teachers (doubtful! maybe the students who take the classnotes) will select the course, write something in the message body, attach the file and hit submit. A mail with the message body and the attachment will get sent to the students in that course.
#Tried it on appengine, working fine, can send mails:). But deleted it quickly from GAE, since no restriction was there on who registers.
#Don't upload it on GAE unless all the issues are fixed.
#Cant be tried on dev_server. Sending mails will work if sendmail is configured on the machine in which the dev_server is running.




import cgi
from xml.dom import minidom
from editable import text

from google.appengine.api import users
from google.appengine.api import mail
from google.appengine.api import urlfetch
from google.appengine.api import memcache

from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app


#Some global variables
HOST_NAME = "msg.iiserk.net"
ADMIN_EMAIL = "mailer-daemon@iiserk.net"
WEBMASTERS = "www@iiserk.net"
ARCHIVE_EMAIL = "iiserk-archives@googlegroups.com "
SENDSPACE_API_KEY = "SSUQMQ7VQC"			#My a/c key, should be replaced by a different a/c
SENDSPACE_API_VER = "1.0"

def getnick():
	"Returns the nickname of the user logged in, or None"
	loggedin = users.get_current_user()
	if loggedin:
		return loggedin.nickname()
	else:
		return None	

def footer():
	"Returns the footer for a particular page."
	loggedin = users.get_current_user()

	if loggedin:
		return '''<div id='footer'>you are logged in as <b>%s</b> (<a href='%s'>logout</a>) \
			</div>\n<a href="http://www.python.org/"><img src="/static/python.png" alt="Python Powered" align="right"/></a><div class="radminfoot">
		<a onmouseover="popup('some idiots from iiser kolkata, do these things when thay have nothing useful to do!')" onmouseout="kill()" title="" onfocus="this.blur()" href="/static/aboutus.txt">&copy;&nbsp;www@iiserk.net</a>
		</div>
		<div class="ladminfoot">
		<a href="/admin">admin area</a>
		</div>
		</div>
		</div></body>
		</html>''' % (loggedin.nickname(), users.create_logout_url("/"))
	return '''<a href="http://www.python.org/"><img src="/static/python.png" alt="Python Powered" align="right"/></a><div class="radminfoot">
		<a onmouseover="popup('some idiots from iiser kolkata, do these things when thay have nothing useful to do!')" onmouseout="kill()" title="" onfocus="this.blur()" href="/static/aboutus.txt">&copy;&nbsp;www@iiserk.net</a>
		</div>
		<div class="ladminfoot">
		<a href="/admin">admin area</a>
		</div>
		</div>
		</div></body>
		</html>'''

class Students(db.Model):			#Stores the student's username, emailaddress and the courses he/she is undertaking
	name = db.StringProperty()
	email = db.EmailProperty()
	courselist = db.StringListProperty()	#Courses are stored as a string list


class Courses(db.Model):
	course = db.TextProperty()		#Stores the course code and some optional jabbering about the course
	about = db.TextProperty()


class HomePage(webapp.RequestHandler):		#Serves the welcome page
	def get(self):
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(text.START_PAGE)

class EmailHomePage(webapp.RequestHandler):		#Serves the welcome page
	def get(self):
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(text.EMAIL_START_PAGE)

class Subscribe(webapp.RequestHandler):		#Allows students to edit the courses they want to recieve about, restricted to iiserk.net a/c
	def get(self):
		formtemplate = text.SUBSCRIBE_FORM
		loggedin = users.get_current_user()
		students = db.GqlQuery("SELECT * FROM Students ORDER BY name")
		flag = 0
		oldcourselist=[]
		for student in students:				#When a student want to edit his/her courselist, delete the previous db entry
			if student.name == loggedin.nickname():
				oldcourselist=student.courselist
				break
		courses = db.GqlQuery("SELECT * FROM Courses")
		options=""
		for course in courses:					#generate the form dynamically from the list of courses.
			if course.course in oldcourselist:
				options = options + '''<option selected>%s</option>'''%(course.course)
			else:
				options = options + '''<option>%s</option>'''%(course.course)
		fullform = formtemplate %(options)
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(fullform+footer())
		

class Subscribed(webapp.RequestHandler):				#Handles the submission of subscription request.
	def post(self):
		loggedin = users.get_current_user()
		students = db.GqlQuery("SELECT * FROM Students ORDER BY name")
		for student in students:				#Delete the previous db entry
			if student.name == loggedin.nickname():
				student.delete()
				break
		self.response.headers['Content-Type'] = 'text/plain'
		selectedcourses=self.request.get('course',allow_multiple=True)
		newstudent = Students()
		newstudent.name = loggedin.nickname()			#save the details in the db
		newstudent.email = loggedin.email()
		newstudent.courselist = selectedcourses
		newstudent.put()
		students = db.GqlQuery("SELECT * FROM Students")

		for student in students:				#unnecessary part, kept for debugging, displays the list of courses the student is subscribed to
			if student.name == loggedin.nickname():
				courselist=student.courselist
				break

		formtemplate = text.SUBSCRIBED_FORM
		listofcourse=""
		for eachcourse in courselist:
			listofcourse = listofcourse +"<li>Course: " + eachcourse + "</li>\n"
		fullform = formtemplate%(listofcourse) + footer()
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(fullform)
		
	def get(self):
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(text.POST_ONLY)


class SendMsgForm(webapp.RequestHandler):				#generates the form to send a message and an attachment to students of a particular course
	def get(self):
		courses = db.GqlQuery("SELECT * FROM Courses")
		formtemplate = text.CREATE_MSG_FORM
		options=""						#Fetch the courses from the db and generate the form dynamically
		for course in courses:
			options = options + '''<option>%s</option>'''%(course.course)
		fullform = formtemplate %('/msgsubmitted',options,"No attachments")
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(fullform+footer())
		


class MsgSubmitted(webapp.RequestHandler):				#handle the msg
	def post(self):
		formcourse = self.request.get('course')
		formsubject = self.request.get('subject')
		formmsg = self.request.get('msgcontent')
		students = db.GqlQuery("SELECT * FROM Students ORDER BY name")
		mailto=[ARCHIVE_EMAIL]				# Default receipient for all mail, this can be a googlegroup address for archiving all mails
		for student in students:
			stu_courses = student.courselist
			if formcourse in stu_courses: mailto.append(student.email)

		message = mail.EmailMessage(sender= ADMIN_EMAIL)		#only admin or loggedin user is allowed to send mails
											#teachers can't be forced to login using iiserk.net a/c
											#so something like automail@iiserk.net should be set as a admin
		message.to = mailto
		message.subject = "[" + formcourse + "] " + formsubject
		message.body = formmsg
		
		if message.is_initialized():						#this returns false if the mail is not proper otherwise returns true
			message.send()							
			formtemplate = text.MAIL_SENT
			addrlist=""
			for addr in mailto:
				addrlist = addrlist+addr+"\n"
			self.response.headers['Content-Type'] = 'text/html'
			self.response.out.write(formtemplate %(addrlist))
		else:
			self.response.out.write("Error, in the message")
			
	def get(self):
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(text.POST_ONLY)
		
		
class Attach(webapp.RequestHandler):			#Uses the sendspace API to send the file
	def get(self):
		uploadurlreq = urlfetch.fetch("http://api.sendspace.com/rest/?method=anonymous.uploadGetInfo&api_key="+SENDSPACE_API_KEY+"&api_version="+SENDSPACE_API_VER)
		response = uploadurlreq.content
		xmlresponse = minidom.parseString(response)
		for node in xmlresponse.getElementsByTagName('upload'):
			uploadurl =  node.getAttribute('url')
			progurl = node.getAttribute('progress_url')
			maxsize = node.getAttribute('max_file_size')
			uploadid = node.getAttribute('upload_identifier')
			xtrainfo = node.getAttribute('extra_info')
		form = text.ATTACH_FORM %(uploadurl,maxsize,uploadid,xtrainfo,"http://"+HOST_NAME+"/attached")
		
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(form+footer())

class Attached(webapp.RequestHandler):
	def get(self):
		fileid = self.request.get('file_id')			#fetch the file_id from the requested url parameters
		courses = db.GqlQuery("SELECT * FROM Courses")
		formtemplate = text.CREATE_MSG_FORM
		options=""						#Fetch the courses from the db and generate the form dynamically
		for course in courses:
			options = options + '''<option>%s</option>'''%(course.course)
		fullform = formtemplate %('/msgsubmitted',options,"Get the attached file here: http://www.sendspace.com/file/" + fileid + " .")
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(fullform+footer())



class AddCourse(webapp.RequestHandler):							#form for course addition
	def get(self):
		formtemplate = text.COURSE_ADD_FORM
		fullform = formtemplate
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(fullform)

class CourseAdded(webapp.RequestHandler):						#processess the form for course addition
											#however it shouldn't be directly added to db, should be first approved by an admin
	def post(self):
		course = self.request.get('course')
		courseabout = self.request.get('courseabout')
		newcourse = Courses()
		newcourse.course = course
		newcourse.about = courseabout
		newcourse.put()
		self.response.headers['Content-Type'] = 'text/plain'
		courses = db.GqlQuery("SELECT * FROM Courses")
		
		for each_course in courses:
			pass
		self.response.out.write("Added the course" + course + "\n" + courseabout)
		
	def get(self):
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(text.POST_ONLY)
		
class RequestCourseAdd(webapp.RequestHandler):
	def get(self):
		formtemplate = text.COURSE_REQUEST_FORM
		fullform = formtemplate
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(fullform+footer())

class RequestSent(webapp.RequestHandler):						#processess the form for course addition
											#however it shouldn't be directly added to db, should be first approved by an admin
	def post(self):
		course = self.request.get('course')
		courseabout = self.request.get('courseabout')
		msgsender = getnick()
		if msgsender == None:
			msgsender=ADMIN_EMAIL
		else:
			msgsender += "@iiserk.net"
		message = mail.EmailMessage(sender=msgsender)
		message.to = WEBMASTERS
		message.subject = "Add this course: "+course
		message.body = courseabout + "\n--mailed by mailer-daemon@iiserk.net"
		message.send()
		formtemplate=text.REQUEST_SENT
		fullform = formtemplate %("Course: " + course + "<br/>" + courseabout)
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(fullform)

	def get(self):
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(text.POST_ONLY)

class Admin(webapp.RequestHandler):
	def get(self):
		html = text.ADMIN_PAGE
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(html)

apps = webapp.WSGIApplication([
				('/',HomePage),
				('/email',EmailHomePage),
				('/admin',Admin),
				('/addcourse',AddCourse),
				('/added',CourseAdded),
				('/requestcourseadd',RequestCourseAdd),
				('/mailrequest', RequestSent),
				('/msg',SendMsgForm),
				('/msgsubmitted',MsgSubmitted),
				('/dropfile',Attach),
				('/attached',Attached),
				('/subscribe', Subscribe),
				('/subscribed', Subscribed)
				],
				debug=False)

def main():
	run_wsgi_app(apps)

if __name__ == "__main__":
	main()
